package com.zdal.sharding.demo.utils;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringFactory {
	
	private static final String ERROR_SPRING_INIT_FAIL = "Spring init fail.";

	private static final Lock mLock = new ReentrantLock();
	private static volatile SpringFactory INSTANCE;

	private ApplicationContext context;

	private SpringFactory() {
	}
	
	/**
	 * 初始化Spring
	 * @param configLocations
	 */
	public void init(String... configLocations) {
		context = new ClassPathXmlApplicationContext(configLocations);
 		AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
        bpp.setBeanFactory(context.getAutowireCapableBeanFactory());
        bpp.processInjection(this);
	}

	/**
	 * 获取Spring的实例
	 * @return   Spring实例
	 */
	public static SpringFactory getInstance() {
		if (INSTANCE == null) {
			try {
				mLock.lock();
				if (INSTANCE == null) {
					INSTANCE = new SpringFactory();
				}
			} finally {
				mLock.unlock();
			}
		}
		return INSTANCE;
	}

	/**
	 * 获取Bean实例
	 * @param beanName  bean 名称
	 * @return          bean 实例
	 */
	public Object getBean(String beanName) {
		if (context == null) {
			throw new RuntimeException(ERROR_SPRING_INIT_FAIL);
		}
		return context.getBean(beanName);
	}
	
	/**
	 * 获取Bean实例
	 * @param clazz
	 * @return
	 */
	public <T> T getBean(Class<T> clazz) {
		if (context == null) {
			throw new RuntimeException(ERROR_SPRING_INIT_FAIL);
		}
		return context.getBean(clazz);
	}
	
	/**
	 * Spring Application Context
	 * @param context
	 */
	public void setApplicationContext(ApplicationContext context) {
		this.context = context;
	}
	

}
